package com.ks.service;

import com.ks.model.Student;
import com.ks.repository.StudentRepo;
import com.ks.service.LogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.transaction.support.TransactionTemplate;

@Service
public class StudentService {
    @Autowired
    private StudentRepo studentRepo;
    @Autowired
    private LogService logService;

    //------------1,默认事务，都回滚了。-----------------------------
    @Transactional
    public void addStudent1(String name){
        try{
            logService.addLog1(name);
        }catch (Exception e){
            e.printStackTrace();
        }
        String txName = TransactionSynchronizationManager.getCurrentTransactionName();
        System.out.println("studentService,txname="+txName);
        studentRepo.save(Student.builder().name(name).build());
    }
    //-----------2，子方法是not_supported,没有事务的，不影响student的方法-----------------------------
    @Transactional
    public void addStudent2(String name){
        try{
            logService.addLog2(name);
        }catch (Exception e){
            e.printStackTrace();
        }
        String txName = TransactionSynchronizationManager.getCurrentTransactionName();
        System.out.println("studentService,txname="+txName);
        studentRepo.save(Student.builder().name(name).build());
    }

    //-------------3，函数式事务，比较麻烦，一般不使用-------
    @Autowired
    private TransactionTemplate transactionTemplate;
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void addStudent3(String name){
        try{
            logService.addLog1(name);
        }catch (Exception e){
            e.printStackTrace();
        }
        String txName = TransactionSynchronizationManager.getCurrentTransactionName();
        System.out.println("studentService,txname="+txName);
        transactionTemplate.execute(status->{
            studentRepo.save(Student.builder().name(name).build());
            //status.flush();
            //用 TransactionStatus 对象的 setRollbackOnly() 方法来回滚事务。
            //status.setRollbackOnly();
            return Boolean.TRUE ;
        });
    }
    //-------------4。自己不加事务，把自己注入进来，后续方法放到事务里。--------
    @Autowired
    private StudentService studentService;
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void addStudent4(String name){
        try{
            logService.addLog1(name);
        }catch (Exception e){
            e.printStackTrace();
        }
        String txName = TransactionSynchronizationManager.getCurrentTransactionName();
        System.out.println("studentService,txname="+txName);
        studentService.saveStudent(name);
        //为啥不用this.saveStudent(name);这样spring会认为是自己内部的方法，就不加事务了！！
    }
    @Transactional
    public void saveStudent(String name){
        String txName = TransactionSynchronizationManager.getCurrentTransactionName();
        System.out.println("studentService,saveStudent,txname="+txName);
        studentRepo.save(Student.builder().name(name).build());
    }

    //------------5,测试非运行时异常。-----------------------------
    @Transactional
    public void addStudent5(String name){
        try{
            logService.addLog3(name);
        }catch (Exception e){
            e.printStackTrace();
        }
        String txName = TransactionSynchronizationManager.getCurrentTransactionName();
        System.out.println("studentService,txname="+txName);
        studentRepo.save(Student.builder().name(name).build());
    }

    //------------6,测试运行时异常。-----------------------------
    @Transactional
    public void addStudent6(String name){
        try{
            logService.addLog4(name);
        }catch (Exception e){
            e.printStackTrace();
        }
        String txName = TransactionSynchronizationManager.getCurrentTransactionName();
        System.out.println("studentService,txname="+txName);
        studentRepo.save(Student.builder().name(name).build());
    }
}
